package com.jeesite.modules.isys.common.aop.query;

import com.baomidou.mybatisplus.annotation.TableName;
import com.jeesite.modules.isys.common.entity.MyPage;
import com.jeesite.modules.isys.common.entity.TimeToLive;
import com.jeesite.modules.isys.common.utils.HutoolCacheUtils;
import io.swagger.models.auth.In;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Aspect
@Component
public class QueryControllerAop {


    //状态码

    //超过最大值
    private static final int OVER_MAX_CODE = 1;

    //未达到最小值
    private static final int NOT_ENOUGH_CODE = 2;

    //正常的状态
    private static final int NORMAL_CODE = 3;



    //拦截mypage
    @Pointcut("execution(com.jeesite.modules.isys.common.entity.MyPage com.jeesite.modules.isys.tb.controller.*.*(..))")
    public void queryControllerAop() {

    }

    @Around("queryControllerAop()")
    public Object queryInsertAopAround(ProceedingJoinPoint joinPoint) throws Throwable {
        //判断方法类型
        String name = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();

        //获取唯一值
        //因为所有的实体都重写了tostring
        String hash = name + "";

        Integer pageNo = 1;
        Integer pageSize = 20;

        hash =  getHash(args);

        //获取分页参数，写死,默认最后两个参数，实在是没办法了
        int length = args.length;
        pageSize = (Integer) args[length - 1];
        pageNo = (Integer) args[length - 2];

        //判断内容是否存在
        Object object = HutoolCacheUtils.get(hash);

        //构建缓存的page
        MyPage tempPage = new MyPage();
        tempPage.setPageNo(pageNo);
        tempPage.setPageSize(pageSize);


        //设置缓存
        for (Object tempObj : args){
            HutoolCacheUtils.put("page"+tempObj.getClass().getName(),tempPage,TimeToLive.CacheTimeToLiveInSeconds);
        }


        if (object == null){
            //执行
            Object proceed = joinPoint.proceed();
            if (proceed instanceof MyPage){
                MyPage page = (MyPage) proceed;
//                //获取当前页
//                 pageNo = page.getPageNo();
//                //获取条数
//                 pageSize = page.getPageSize();

                //获取数据
                Object list = page.getList();

                //储存数据
                HutoolCacheUtils.put(hash,list, TimeToLive.CacheTimeToLiveInSeconds);

                //获取需要的数据
                List listSub = execListSub(list, pageNo, pageSize);

                if (listSub == null){
                    //数据不够
                    return joinPoint.proceed();
                }


                //设置数据
                page.setList(listSub);
                page.setPageNo(pageNo);
                page.setPageSize(pageSize);
                page.setCount(listSub.size());


                page.setTotal(getTotal((List) list));

                return page;
            }
        }else {
            //构造page
            MyPage myPage = new MyPage();
            List list = execListSub(object,pageNo,pageSize);

            if (list == null){
                //数据不够，重新查询
               return   joinPoint.proceed();
            }
            myPage.setList(list);
            myPage.setPageNo(pageNo);
            myPage.setPageSize(pageSize);
            myPage.setCount(list.size());
            myPage.setTotal(getTotal((List) list));

            return myPage;
        }
        return joinPoint.proceed();
    }


    private Integer getTotal(List list){


        if (list.isEmpty()){
            return 0;
        }

        Object object = list.get(0);


        if (object == null){
            return 0;
        }

        Object totalObj = HutoolCacheUtils.get("total" + object.getClass().getName());

        if (totalObj == null){
            return list.size();
        }

        return (Integer) totalObj;
    }
    private String getHash(Object... args) {

        String hash = "";


        //计数
        Integer count = 0;
        Integer length = args.length;

        //计算结束值
        Integer num = length - 3;

        for (Object object :args){
//            if (object.getClass().getAnnotation(TableName.class)!=null){
//                hash += object.toString();
//            }

            hash += object.toString();


            if (count == num){
                break;
            }

            //计数器加一
            count++;
        }

        return hash;

    }


    //判断状态值
    private  int  check(Object list,Integer start,Integer end){

        List tempList =  (List) list;

        //当前主列表长度小于当前需要的长度
        if (tempList.size() <= end){
            //需求的最大的长度大于最大长度
            return OVER_MAX_CODE;
        }

        if (tempList.size() < start){
            //需求的最小长度大于最大长度
            return NOT_ENOUGH_CODE;
        }

        //否则就是正常状态
        return NORMAL_CODE;
    }

    private List execListSub(Object list,Integer pageNo,Integer pageSize) {

        //正常状态
        List tempList =  (List) list;

        //计算开始值
        Integer start = (pageNo - 1) * pageSize;

        //计算结束值
        Integer end = pageNo * pageSize - 1;

        //计算状态
        int check = check(list, start, end);

        if (check == OVER_MAX_CODE){
            //超过最大值,end应该为最大值
            end = ((List<?>) list).size() - 1;
        }

        if (check == NOT_ENOUGH_CODE){
            //未达到最小值,需要重新查询
            return null;
        }

        //正常状态
        List resList = tempList.subList(start, end + 1);
        return resList;

    }

}
